package com.sunlands.zlcx.usercenter.util.image;


import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.sunlands.zlcx.usercenter.constant.PicEnum;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.util.*;
import java.util.List;

import static com.sunlands.zlcx.usercenter.constant.PicEnum.logoPath;

@Slf4j
public class QrcodeUtils {



    static byte[] logoBytes;
    static List<byte[]> bgBytes = new ArrayList<>();

    ;//logo路径

//    public static final String bgPath = "/Users/imaginary/tongzhuo-share1.png";//logo路径

    /**
     * 画二维码
     *
     * @param qrcodePath 存放二维码路径
     * @param content    二维码内容
     * @param height     二维码高度
     * @param width      二维码宽度
     */
    public static void drawQrcode(String qrcodePath, String content, int height, int width) {
        try {
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
            //设置UTF-8， 防止中文乱码
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            //设置二维码四周白色区域的大小
            hints.put(EncodeHintType.MARGIN, 0);
            //设置二维码的容错性
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            //画二维码，记得调用multiFormatWriter.encode()时最后要带上hints参数，不然上面设置无效
            BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
            //qrcFile用来存放生成的二维码图片（无logo，无文字）
            File qrcodeFile = QrcodeUtils.findFile(qrcodePath);
            //开始画二维码
            MatrixToImageWriter.writeToFile(bitMatrix, "jpg", qrcodeFile);
        } catch (WriterException | IOException e) {
            log.error("", e);
        }
    }

    /**
     * 给二维码图片添加Logo
     *
     * @param qrCodeByte 二维码路径
     * @param logoByte   logo路径
     * @param logoConfig logo 配置文件
     */
    public static byte[] addLogoToQRCode(byte[] qrCodeByte, byte[] logoByte, LogoConfig logoConfig) {
        try {
            //读取二维码图片，并构建绘图对象
            BufferedImage image = ImageIO.read(new ByteArrayInputStream(qrCodeByte));
            Graphics2D g = image.createGraphics();
            //读取logo文件
            BufferedImage logo = ImageIO.read(new ByteArrayInputStream(logoByte));
            //设置logo的位置
            int widthLogo = image.getWidth() / logoConfig.getLogoPart();
            int heightLogo = image.getWidth() / logoConfig.getLogoPart(); // 保持二维码是正方形的
            // 计算图片放置位置（居中）
            int x = (image.getWidth() - widthLogo) / 2;
            int y = (image.getHeight() - heightLogo) / 2;

            // 开始绘制图片
            g.drawImage(logo, x, y, widthLogo, heightLogo, null);
            g.drawRoundRect(x, y, widthLogo, heightLogo, 10, 10);
            g.setStroke(new BasicStroke(logoConfig.getBorder()));
            g.setColor(logoConfig.getBorderColor());
            g.drawRect(x, y, widthLogo, heightLogo);
            g.dispose();
            return imageToBytes(image);
        } catch (Exception e) {
            log.error("", e);
        }
        return null;
    }

    /**
     * 画二维码
     *
     * @param content 二维码内容
     * @param height  二维码高度
     * @param width   二维码宽度
     */
    public static byte[] drawQrcode(String content, int height, int width) {
        byte[] imagesStream = null;
        try {
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
            //设置UTF-8， 防止中文乱码
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            //设置二维码四周白色区域的大小
            hints.put(EncodeHintType.MARGIN, 2);
            //设置二维码的容错性
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            //画二维码，记得调用multiFormatWriter.encode()时最后要带上hints参数，不然上面设置无效
            BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
            //qrcFile用来存放生成的二维码图片（无logo，无文字）
            //开始画二维码

            ByteArrayOutputStream outputStream = null;
            try {
                outputStream = new ByteArrayOutputStream();
                MatrixToImageWriter.writeToStream(bitMatrix, "jpg", outputStream);
            } catch (Exception e) {

            } finally {
                if (outputStream != null) {
                    outputStream.close();
                }
            }
            imagesStream = outputStream.toByteArray();
        } catch (WriterException | IOException e) {
            log.error("", e);
        }
        return imagesStream;
    }

    private static byte[] imageToBytes(BufferedImage bImage) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ImageIO.write(bImage, "png", out);
        } catch (IOException e) {
            log.error("", e);
        }
        return out.toByteArray();
    }


    public static void main(String[] args) {
        String content = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxeb6be10fec237b67&redirect_uri=https://tongzhuotest.sunlands.wang/tz-user-center/users/invite&response_type=code&scope=snsapi_userinfo&state=1919284,3&connect_redirect=1&friendsType=1";
        byte[] drawQrcode = QrcodeUtils.drawQrcode(content, 100, 100);
        byte[] logoToQRCode = QrcodeUtils.addLogoToQRCode(drawQrcode, QrcodeUtils.getLogo(), new LogoConfig());

    }

    /**
     * @param qrcodePath     二维码路径
     * @param width          文字二维码宽度
     * @param height         文字二维码高度
     * @param qrcodeFontList 文字内容集合
     * @给二维码添加文字
     */
    public static File pressText(byte[] qrcodePath, byte[] bgPath, int width, int height, List<QrcodeFont> qrcodeFontList) {
        try {
            Image src = ImageIO.read(new ByteArrayInputStream(qrcodePath));
            BufferedImage image = ImageIO.read(new ByteArrayInputStream(bgPath));
            Image from = image.getScaledInstance(width, height, Image.SCALE_DEFAULT);
            Graphics2D g = image.createGraphics();
            image = g.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
            g.dispose();
            g = image.createGraphics();

            g.drawImage(from, 0, 0, width, height, null);
            g.drawImage(src, width - 100 - 40, height - 100 - 20, 100, 100, null);

            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
            for (QrcodeFont qrcodeFont : qrcodeFontList) {
                g.setColor(qrcodeFont.getColor());
                g.setFont(new Font("黑体", qrcodeFont.getFontStyle(), qrcodeFont.getFontSize()));
                g.drawString(qrcodeFont.getText(), qrcodeFont.getStartX(), qrcodeFont.getStartY());
            }
            g.dispose();
            File tempFile = File.createTempFile(UUID.randomUUID().toString(), ".png");
            ImageIO.write(image, "png", tempFile);
            return tempFile;
        } catch (Exception e) {
            log.error("", e);
        }
        return null;
    }


    public static byte[] getLogo() {
        if (Objects.nonNull(logoBytes)) {
            log.info("文件为空！");
            return logoBytes;
        }
        File file = new File(logoPath);
        try {
            logoBytes = Files.readAllBytes(file.toPath());
        } catch (IOException e) {
            log.error("", e);
        }
        return logoBytes;
    }

    public static byte[] getBg(Integer index) {
        if (Objects.nonNull(bgBytes) && !bgBytes.isEmpty() && bgBytes.size() > index) {
            return bgBytes.get(index);
        }
        synchronized (PicEnum.class) {
            //双重检查
            if (Objects.nonNull(bgBytes) && !bgBytes.isEmpty() && bgBytes.size() > index) {
                throw new IndexOutOfBoundsException("图片索引数超出提供的图片模板数量 index = " +index);
            }
            Arrays.stream(PicEnum.values()).forEach(pic -> {
                File file = new File(pic.getPath());
                try {
                    byte[] bgByte = Files.readAllBytes(file.toPath());
                    bgBytes.add(bgByte);
                } catch (IOException e) {
                    log.error("", e);
                }
            });
        }
        return bgBytes.get(index);
    }


    /**
     * @param filepath
     * @return
     * @查找文件（没有则创建文件）
     */
    public static File findFile(String filepath) {
        File file = new File(filepath);
        if (!file.exists()) {
            file.mkdir();
        }
        return file;
    }


}
